package com.cs249.hiep;

import java.util.concurrent.ConcurrentSkipListSet;

public class Node implements Comparable<Node> {

	private int id = 0;

	private Node parent;

	private boolean root = false;

	private ConcurrentSkipListSet<Node> children = new ConcurrentSkipListSet<Node>();

	private ConcurrentSkipListSet<Node> unexplored = new ConcurrentSkipListSet<Node>();

	private boolean terminated;

	public boolean isTerminated() {
		return terminated;
	}

	public void setTerminated(boolean terminated) {
		this.terminated = terminated;
	}

	public boolean isRoot() {
		return root;
	}

	public void setRoot(boolean root) {
		this.root = root;
	}

	public int getId() {
		return id;
	}

	public void setId(int id) {
		this.id = id;
	}

	public Node getParent() {
		return parent;
	}

	public void setParent(Node parent) {
		this.parent = parent;
	}

	public void addNeighbor(Node neighbor) {
		unexplored.add(neighbor);
	}

	public void sendFrom(Node node, Message message) {
		if (terminated) {
			return;
		}

		if (message instanceof AlreadyMessage) {
			explore();

		} else if (message instanceof ParentMessage) {
			children.add(node);
			explore();

		} else {
			if (parent == null) {
				parent = node;

				removeFromUnexplored(node);

				explore();
			} else {
				node.sendFrom(this, new AlreadyMessage());
				unexplored.remove(node);
			}
		}
	}

	private synchronized void removeFromUnexplored(Node node) {
		for (Node n : unexplored) {
			if (n.getId() == node.getId()) {
				unexplored.remove(n);
			}
		}
	}

	public void explore() {
		for (Node node : unexplored) {
			unexplored.remove(node);
			node.sendFrom(this, new Message());
		}

		if (parent != this) {
			parent.sendFrom(this, new ParentMessage());
			terminated = true;
		}

	}

	public void addChild(Node child) {
		children.add(child);
	}

	// @Override
	// public void run() {
	// // TODO Auto-generated method stub
	// if (isRoot()) {
	// explore();
	// }
	//
	// }

	public String toString() {
		if (parent != null) {

		}
		return "Node " + getId() + ", terminate=" + isTerminated()
				+ ", children=" + children;
	}

	@Override
	public int compareTo(Node o) {
		// TODO Auto-generated method stub
		if (o == null) {
			return 1;
		}

		if (this.id < o.id) {
			return 1;
		}

		if (this.id > o.id) {
			return -1;
		}

		return 0;
	}
}
